home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
windownt
/
wvnsrc75.zip
/
WVHEADER.C
< prev
next >
Wrap
Text File
|
1992-11-09
|
22KB
|
877 lines
/* --- WVHEADER.C ---------------------------------------------
*
* This file contains the code necessary to create the initial skeleton
* version of an article, which will be edited by the user.
*
* Mark Riordan 24-JAN-1990
*/
#include "windows.h"
#include "wvglob.h"
#include "winvn.h"
#ifndef MAC
#include "winundoc.h"
#include <ctype.h>
#include <time.h>
#endif
#define MAXHEADERLINE 256
BOOL (*PostHeaderFuncs[])(TypDoc * Doc, char *Buf, long int BufLen) =
{
MakeArtHeaderFrom,
MakeArtHeaderNewsgroups,
MakeArtHeaderSubject,
/* MakeArtHeaderMessageID, */
/* MakeArtHeaderDate, */
MakeArtHeaderReferences,
MakeArtHeaderOrganization,
/* MakeArtHeaderNewsreader, */
NULL
};
BOOL (*MailHeaderFuncs[])(TypDoc * Doc, char *Buf, long int BufLen) =
{
MakeArtHeaderTo,
MakeArtHeaderFrom,
MakeArtHeaderSubject,
MakeArtHeaderOrganization,
NULL
};
/*--- function GetHeaderLine -------------------------------------------
*
* Given a document, get a line from the header portion of that document
* whose prefix matches a given prefix. Prefix = first word in line.
* For instance, you might call this routine to say "Get the 'Subject:'"
* line from this document.
*
* Entry Doc points to the document whose header we are scanning.
* The header is all the lines up to the first blank line.
* Prefix is the character string which will identify the
* line we are seeking. It is the first word
* (blank-delimited) in a line in the header.
* BufLen is the number of bytes left in the buffer Buf.
*
* Exit Returns TRUE iff we returned a line.
* Buf if line was returned, contains that line, zero-
* terminated.
*/
BOOL
GetHeaderLine (Doc, Prefix, Buf, BufLen)
TypDoc *Doc;
char *Prefix;
char *Buf;
int BufLen;
{
char *bufptr = Buf;
TypBlock far *BlockPtr;
TypLine far *LinePtr;
unsigned int Offset;
HANDLE hBlock;
TypLineID MyLineID;
int found = FALSE;
TopOfDoc (Doc, &BlockPtr, &LinePtr);
while (ExtractTextLine (Doc, LinePtr, Buf, BufLen))
{
/* Is this a blank line signifying the end of the header? */
if (IsLineBlank (Buf))
break;
if (CompareStringNoCase (Buf, Prefix, strlen (Prefix)) == 0)
{
found = TRUE;
break;
}
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
return (found);
}
/*--- function CreatePostingWnd -----------------------------------------
*
* Create the window for composing the text of a posting,
* if it's OK to post.
*
* Entry Doc points to the document to which we are posting
* a followup--NULL if it's a new posting.
*
* Exit Returns the handle of the newly-created window
* (zero if failure).
*/
HWND
CreatePostingWnd (Doc, DocType)
TypDoc *Doc;
int DocType;
{
int ih;
BOOL found = FALSE;
HWND hWnd = 0;
int width, AveCharWidth;
HDC hDC;
#ifndef MAC
TEXTMETRIC tmFontInfo;
#endif
char *TitlePtr, *WndName;
if (DocType == DOCTYPE_POSTING)
{
WndName = "WinVnPost";
PostDoc = Doc;
if (Doc)
{
TitlePtr = "Composing Followup Article";
}
else
{
TitlePtr = "Composing New Article";
}
for (ih = 0; !found && ih < MAXPOSTWNDS; ih++)
{
if (!hWndPosts[ih])
{
found = TRUE;
break;
}
}
}
else
{
WndName = "WinVnMail";
MailDoc = Doc;
if (Doc)
{
TitlePtr = "Composing Reply Message";
}
else
{
TitlePtr = "Composing New Mail Message";
}
for (ih = 0; !found && ih < MAXMAILWNDS; ih++)
{
if (!hWndMails[ih])
{
found = TRUE;
break;
}
}
}
if (found && AuthenticatePosting ())
{
#ifndef MAC
hDC = GetDC (hWndConf);
GetTextMetrics (hDC, (LPTEXTMETRIC) & tmFontInfo);
AveCharWidth = tmFontInfo.tmAveCharWidth;
ReleaseDC (hWndConf, hDC);
if (xScreen > 78 * AveCharWidth)
{
width = 78 * AveCharWidth;
}
else
{
width = xScreen - 2 * AveCharWidth;
}
#else
width = xScreen - 20;
#endif
hWnd = CreateWindow (WndName,
TitlePtr,
WS_OVERLAPPEDWINDOW /* | WS_VSCROLL */ ,
ih * CharWidth, /* Initial X pos */
(int) (yScreen * 3 / 8) + (1 + ih) * LineHeight, /* Initial Y pos */
(int) width, /* Initial X Width */
(int) (yScreen * 5 / 8) - (2 * LineHeight), /* Initial Y height */
NULL,
NULL,
hInst,
NULL);
if (hWnd)
{
#ifndef MAC
ShowWindow (hWnd, SW_SHOWNORMAL);
#else
MyShowWindow (hWnd, SW_SHOWNORMAL);
#endif
UpdateWindow (hWnd);
}
}
return (hWnd);
}
/*--- function CreatePostingText ------------------------------------------
*
* Create the text of the skeleton article to be edited by
* the user before posting. Display that text in an edit window.
*/
BOOL
CreatePostingText (Doc, hWndPost, hWndEdit, DocType)
TypDoc *Doc;
HWND hWndPost;
HWND hWndEdit;
int DocType;
{
long int BytesLeft;
char far *lpTextBuffer;
char far *lpCurPtr;
HANDLE hTextBuffer;
BOOL gotline;
char line[MAXHEADERLINE];
int ifunc;
int nLines;
long lParam;
int RefCount;
BOOL found;
BOOL (**HeaderFuncs) (TypDoc * Doc, char *Buf, long int BufLen);
#ifdef MAC
long int textLength;
TEHandle TEH;
int ih;
Rect viewRect, destRect;
#endif
if (DocType == DOCTYPE_POSTING)
{
HeaderFuncs = PostHeaderFuncs;
}
else
{
HeaderFuncs = MailHeaderFuncs;
}
/* Compute the number of bytes we need to hold a straight ASCII representation
* of the initial text of the reply, and allocate a buffer of that size.
*/
found = 0;
if (Doc)
{
BytesLeft = (2 + NumBlocksInDoc (Doc)) * Doc->BlockSize;
}
else
{
BytesLeft = 3000;
}
if (NULL == (hTextBuffer = GlobalAlloc (GHND, (DWORD) BytesLeft)))
{
MessageBox (hWndPost, "Cannot allocate memory for text", "", MB_OK);
return FALSE;
}
lpCurPtr = lpTextBuffer = GlobalLock (hTextBuffer);
for (ifunc = 0; HeaderFuncs[ifunc]; ifunc++)
{
gotline = (HeaderFuncs[ifunc]) (Doc, line, (long int) MAXHEADERLINE);
if (gotline)
{
AppendTextToEditBuf (line, &lpCurPtr, &BytesLeft);
}
}
MakeArtBody (Doc, &lpCurPtr, &BytesLeft, DocType);
/* Set the edit window text to this skeleton article. */
#ifndef MAC
SetWindowText (hWndEdit, lpTextBuffer);
#else
viewRect = hWndPost->portRect;
viewRect.right -= SBarWidth;
viewRect.bottom -= SBarWidth;
destRect = viewRect;
destRect.left = 3;
SetPort (hWndPost);
TEH = TENew (&destRect, &viewRect);
TEHCurrent = TEH;
(*TEH)->crOnly = -1;
textLength = lstrlen (lpTextBuffer);
TESetText (lpTextBuffer, textLength, TEH);
SetView (hWndPost);
ShowSelect (hWndPost);
TEUpdate (&destRect, TEH);
for (ih = 0, found = FALSE; !found && ih < MAXPOSTWNDS; ih++)
{
if (hWndPosts[ih] == hWndPost)
{
TEHPosts[ih] = TEH;
found = TRUE;
break;
}
}
/* mrr add here */
#endif
GlobalUnlock (hTextBuffer);
GlobalFree (hTextBuffer);
#if 0
strcpy (mesbuf, "Winc - Viewing ");
strncat (mesbuf, NewMemos[imemo], MAXMEMONAME);
SetWindowText (hWnd, mesbuf);
#endif
#ifndef MAC
nLines = (int) SendMessage (hWndEdit, EM_GETLINECOUNT, 0, 0L);
lParam = (long) ((long) nLines);
/* while(nLines--) SendMessage(hWndEdit,WM_KEYDOWN,VK_DOWN,0L); */
#endif
return TRUE;
}
/*--- functions MakeArtHeaderXXXXX ---------------------------------------
*
* Functions with names of the form MakeArtHeaderXxxxxx are all called
* the same way and have similar purposes. They are called to
* create and return a line of text that will become a line in
* the header of an article to be posted. The source of
* this information varies; it may be taken from an article
* being replied to, it may be taken from a configuration file,
* read from the system clock, etc.
*
* Entry Doc points to a document containing an article
* being replied to; NULL if we're not replying
* to an article.
* BufLen is the length of the output buffer.
*
* Exit Returns TRUE iff we returned a line.
* Buf contains the line, if any, terminated by a
* zero byte.
*/
/*--- function MakeArtHeaderSubject -------------------------------------
*
* Returned "Subject:" line is blank if no previous Subject: line
* could be found. Otherwise, it is "Subject: Re: <previous subject>".
* If the article being replied to had a subject already starting
* with "Re:", the "Re:" is not repeated.
*/
BOOL
MakeArtHeaderSubject (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
BOOL gotline;
char *outptr = Buf;
char *headptr = HeadLine;
CopyBuf ("Subject: ", &outptr, &BufLen);
if (Doc)
{
gotline = GetHeaderLine (Doc, "Subject:", HeadLine, MAXHEADERLINE);
if (gotline)
{
NextToken (&headptr);
if (CompareStringNoCase (headptr, "Re:", 3) != 0)
{
CopyBuf ("Re: ", &outptr, &BufLen);
}
CopyBuf (headptr, &outptr, &BufLen);
}
else
{
DialogBox (hInst, "WinVnSubject", Doc->hDocWnd, lpfnWinVnSubjectDlg);
CopyBuf (SubjectString, &outptr, &BufLen);
}
}
else
{
DialogBox (hInst, "WinVnSubject", hWndConf, lpfnWinVnSubjectDlg);
CopyBuf (SubjectString, &outptr, &BufLen);
}
return (TRUE);
}
#if 0
/*--- function MakeArtHeaderMessageID ----------------------------------
*
* Returned "Message-ID:" line is computed from the time and
* the ServerName (from Windows profile file). This needs to
* be improved.
*/
BOOL
MakeArtHeaderMessageID (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
#define MAXSERVERNAME 32
char ServerName[MAXSERVERNAME];
GetPrivateProfileString (szAppName, "ServerName", "titan.ksc.nasa.gov",
ServerName, MAXSERVERNAME, szAppProFile);
sprintf (Buf, "Message-ID: <%ld@%s>", time ((time_t *) NULL), ServerName);
return TRUE;
}
#endif
/*--- function MakeArtHeaderFrom ----------------------------------
*
* Returned "From:" is taken from Windows profile entries.
*/
BOOL
MakeArtHeaderFrom (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
CopyBuf ("From: ", &outptr, &BufLen);
if (MailAddress[0])
{
CopyBuf (MailAddress, &outptr, &BufLen);
}
else
{
CopyBuf ("<Unknown>", &outptr, &BufLen);
}
if (UserName[0])
{
CopyBuf (" (", &outptr, &BufLen);
CopyBuf (UserName, &outptr, &BufLen);
CopyBuf (")", &outptr, &BufLen);
}
return TRUE;
}
/*--- function MakeArtHeaderTo ----------------------------------
*
* Simply returns a blank "To:" line.
*/
BOOL
MakeArtHeaderTo (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
char *outptr = Buf, *cptr = HeadLine;
BOOL gotwho;
CopyBuf ("To: ", &outptr, &BufLen);
if (Doc)
{
gotwho = GetHeaderLine (Doc, "Reply-To:", HeadLine, MAXHEADERLINE);
if (!gotwho)
{
gotwho = GetHeaderLine (Doc, "From:", HeadLine, MAXHEADERLINE);
}
if (gotwho)
{
NextToken (&cptr);
while (*cptr && *cptr != ' ')
{
*(outptr++) = *(cptr++);
}
*outptr = '\0';
}
}
return TRUE;
}
/*--- function MakeArtHeaderOrganization ----------------------------------
*
* Returned "Organization:" line is gotten from the Windows
* profile file.
*/
BOOL
MakeArtHeaderOrganization (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
if (Organization[0])
{
CopyBuf ("Organization: ", &outptr, &BufLen);
CopyBuf (Organization, &outptr, &BufLen);
return (TRUE);
}
return FALSE;
}
/*--- function MakeArtHeaderNewsreader ----------------------------------
*
* Returned "Newsreader: " line is simply a constant.
*/
BOOL
MakeArtHeaderNewsreader (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
CopyBuf ("Newsreader: ", &outptr, &BufLen);
CopyBuf ("MS Windows ", &outptr, &BufLen);
CopyBuf (szAppName, &outptr, &BufLen);
/* easier than examining this closely */
CopyBuf ("\r", &outptr , &BufLen);
return (TRUE);
}
#if 0
/*--- function MakeArtHeaderDate ----------------------------------
*
* Returned "Date:" line is computed from operating system time.
* Be sure to set the TZ environment variable correctly for
* "grtime" to work properly. Typical setting: SET TZ=EST5
*/
BOOL
MakeArtHeaderDate (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
struct tm *timeptr;
time_t curtime;
curtime = time ((time_t *) NULL);
timeptr = gmtime (&curtime);
sprintf (Buf, "Date: %.4d-%.2d-%.2d %.2d:%.2d GMT", timeptr->tm_year + 1900,
timeptr->tm_mon + 1, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min);
return TRUE;
}
#endif
/*--- function MakeArtHeaderReferences -----------------------------------
*
* Returned "References:" line contains all the previous article's
* References (if any), plus its Message-ID (if any).
*/
BOOL
MakeArtHeaderReferences (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
BOOL gotrefs;
BOOL gotmesID;
char *outptr = Buf;
char *headptr = HeadLine;
if (Doc)
{
gotrefs = GetHeaderLine (Doc, "References:", HeadLine, MAXHEADERLINE);
if (gotrefs)
{
CopyBuf (HeadLine, &outptr, &BufLen);
CopyBuf (" ", &outptr, &BufLen);
}
gotmesID = GetHeaderLine (Doc, "Message-ID:", HeadLine, MAXHEADERLINE);
if (gotmesID)
{
if (!gotrefs)
{
CopyBuf ("References: ", &outptr, &BufLen);
}
NextToken (&headptr);
CopyBuf (headptr, &outptr, &BufLen);
}
if (gotrefs || gotmesID)
return (TRUE);
}
return FALSE;
}
/*--- function MakeArtHeaderNewsgroups -----------------------------------
*
* Returned "Newsgroups:" line is simply a copy of previous article's.
*/
BOOL
MakeArtHeaderNewsgroups (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
BOOL gotnews = FALSE;
char *outptr = Buf;
if (Doc)
{
gotnews = GetHeaderLine (Doc, "Newsgroups:", HeadLine, MAXHEADERLINE);
if (gotnews)
{
CopyBuf (HeadLine, &outptr, &BufLen);
}
}
if (!gotnews)
{
CopyBuf ("Newsgroups: ", &outptr, &BufLen);
CopyBuf (NewsgroupsPtr, &outptr, &BufLen);
}
return TRUE;
}
/*--- function MakeArtBody ----------------------------------------------
*
* Make the body of the article. This is null if there's no article
* to reply to, else it's text of the form:
* In article <Message-ID>, <user> says:
* >line 1
* >line 2
* > .....
*
* Entry Doc points to the article being replied to, else
* NULL if none.
* left is the number of bytes left in MesBuf.
*
* Exit MesBuf contains the added lines, and has been updated
* to point to just after the last added byte.
* left has been decremented appropriately.
* Return value is not used, for now.
*/
BOOL
MakeArtBody (Doc, MesBuf, left, DocType)
TypDoc *Doc;
char far **MesBuf;
long int *left;
int DocType;
{
HANDLE hBlock;
unsigned int Offset;
TypLineID MyLineID;
TypBlock far *BlockPtr;
TypLine far *LinePtr;
char mesID[MAXHEADERLINE];
char from[MAXHEADERLINE];
char line[MAXHEADERLINE];
BOOL gotmesID, gotfrom;
char *outptr = line;
char *fromptr = from;
char *mesptr = mesID;
AppendTextToEditBuf ("", MesBuf, left); /* blank line after header */
/* Create the "In message xxx, yyy says:" line. */
if (Doc)
{
gotmesID = GetHeaderLine (Doc, "Message-ID:", mesID, MAXHEADERLINE);
if (gotmesID)
{
NextToken (&mesptr);
}
else
{
mesptr = "<Unknown>";
}
if (DocType == DOCTYPE_POSTING)
{
gotfrom = GetHeaderLine (Doc, "From:", from, MAXHEADERLINE);
if (gotfrom)
{
NextToken (&fromptr);
}
else
{
fromptr = "<Unknown>";
}
sprintf (line, "In article %s, %s says:", mesptr, fromptr);
}
else
{
sprintf (line, "In article %s, you say:", mesptr);
}
AppendTextToEditBuf (line, MesBuf, left);
/* Skip past header of reply document. */
TopOfDoc (Doc, &BlockPtr, &LinePtr);
while (ExtractTextLine (Doc, LinePtr, line, MAXHEADERLINE) &&
!IsLineBlank (line))
{
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
/* Copy body of reply document into the body of this article, */
/* prepending a ">" to each line. */
line[0] = '>';
while (ExtractTextLine (Doc, LinePtr, line + 1, MAXHEADERLINE - 1))
{
AppendTextToEditBuf (line, MesBuf, left);
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
}
return TRUE;
}
/*--- function CompareStringNoCase -------------------------------------
*
* Compare two strings, case insensitive.
*
* Entry str1, str2 are two strings to compare.
* slen is the number of characters to compare
* (but stop at a zero byte).
*
* Exit returns -1 if str1 is earlier in collating sequence,
* 0 if strings are equal, 1 otherwise
*/
int
CompareStringNoCase (str1, str2, slen)
char *str1;
char *str2;
int slen;
{
while (slen-- && *str1 && *str2)
{
if (_tolower (*str1) < _tolower (*str2))
{
return (-1);
}
else if (_tolower (*str1) > _tolower (*str2))
{
return (1);
}
str1++;
str2++;
}
return (0);
}
/*--- function CopyBuf -----------------------------------------------
*
* Copy a string into a buffer, being sure not to overrun the
* buffer.
*
* Entry instr points to the string to copy into the buffer,
* zero-terminated.
* buf is the buffer
* left is the number of bytes left in the buffer
* Exit buf contains the LWA+1 of the bytes copied into
* the output buffer. A Zero byte is stored
* into this location.
* left is the number of bytes left in the buffer.
*/
void
CopyBuf (instr, buf, left)
char *instr;
char **buf;
long int *left;
{
while (--(*left) > 1 && *instr)
{
*((*buf)++) = *(instr++);
}
if (*left > 0)
**buf = '\0';
}
/*--- function NextToken -----------------------------------------------
*
* Position a pointer to the next token in a string.
* Delimiters are space and tab.
*
* Entry cptr points to a position in a zero-terminated string.
*
* Exit Returns TRUE iff a next token was found.
* cptr points to the next token, if found--else
* it is unchanged.
*/
BOOL
NextToken (cptr)
char **cptr;
{
/* Skip to end of current token, if any. */
while (**cptr != ' ' && **cptr != '\t' && **cptr)
(*cptr)++;
/* Skip past white space. */
while (**cptr && (**cptr == ' ' || **cptr == '\t'))
(*cptr)++;
if (**cptr)
{
return (TRUE);
}
else
{
return (FALSE);
}
}
/*--- function AppendTextToEditBuf ----------------------------------------
*
* Appends a zero-terminated text line to a buffer to be given
* to an Edit window. Used in building messages to be displayed
* and edited by an Edit window.
*
* Entry instr points to a text line to add. It is terminated
* by a zero byte and does not end in CR or LF.
* left is the number of characters left in buf.
*
* Exit buf contains the line, terminated by CR and LF.
* buf now points to the next available byte.
* left has been decremented as appropriate.
*/
void
AppendTextToEditBuf (instr, buf, left)
char *instr;
char far **buf;
long int *left;
{
while (--(*left) > 0 && *instr)
{
*((*buf)++) = *(instr++);
}
if (--(*left) > 0)
*((*buf)++) = '\r';
#ifndef MAC
if (--(*left) > 0)
*((*buf)++) = '\n';
#endif
if ((*left) > 0)
**buf = '\0';
}
/*--- function IsLineBlank ------------------------------------------------
*
* Determine whether a zero-terminated line is blank.
* "Blank" means it contains nothing but spaces and tabs.
*
* Entry line points to the line.
*
* Exit returns TRUE iff the line is blank.
*/
BOOL
IsLineBlank (line)
char far *line;
{
while (*line == ' ' || *line == '\t' || *line == '\n')
line++;
return (!(*line));
}